// 《围棋》作者版权所有。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// 包httptest为HTTP测试提供实用程序。
package httptest

import (
	"bufio"
	"bytes"
	"crypto/tls"
	"io"
	"net/http"
	"strings"
)

// NewRequest返回一个新的传入服务器请求，适用于传递给http的
// 。用于测试的处理器。
// 
// 目标是RFC 7230“请求目标”：它可以是
// 路径或绝对URL。如果target是绝对URL，则使用URL中的主机名
// 。否则使用“example.com”。
// 
// 如果目标具有方案
// “https”，则TLS字段设置为非零伪值。
// 
// 请求。Proto总是HTTP/1.1。
// 
// 空方法表示“GET”。
// 
// 提供的正文可能为零。如果正文的类型为*字节。读卡器，
// /*字符串。读卡器，或*字节。缓冲区，请求。ContentLength是
// 集。
// 
// NEWLEST因错误而恐慌，以便于在测试中使用，
// 恐慌是可以接受的。
// 
// 要生成客户端HTTP请求而不是服务器请求，请参阅
// net/HTTP包中的NewRequest函数。
func NewRequest(method, target string, body io.Reader) *http.Request {
	if method == "" {
		method = "GET"
	}
	req, err := http.ReadRequest(bufio.NewReader(strings.NewReader(method + " " + target + " HTTP/1.0\r\n\r\n")))
	if err != nil {
		panic("invalid NewRequest arguments; " + err.Error())
	}

	// HTTP/1.0用于避免需要主机字段。这里改成1.1。
	req.Proto = "HTTP/1.1"
	req.ProtoMinor = 1
	req.Close = false

	if body != nil {
		switch v := body.(type) {
		case *bytes.Buffer:
			req.ContentLength = int64(v.Len())
		case *bytes.Reader:
			req.ContentLength = int64(v.Len())
		case *strings.Reader:
			req.ContentLength = int64(v.Len())
		default:
			req.ContentLength = -1
		}
		if rc, ok := body.(io.ReadCloser); ok {
			req.Body = rc
		} else {
			req.Body = io.NopCloser(body)
		}
	}

	// 192.0.2.0/24是RFC 5737中的“测试网”，仅用于
	// 文档和示例源代码，不应公开使用。
	req.RemoteAddr = "192.0.2.1:1234"

	if req.Host == "" {
		req.Host = "example.com"
	}

	if strings.HasPrefix(target, "https:// /”{
		req.TLS = &tls.ConnectionState{
			Version:           tls.VersionTLS12,
			HandshakeComplete: true,
			ServerName:        req.Host,
		}
	}

	return req
}
